package com.hoperun.framework.ex.resolver;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.hoperun.framework.ex.AccessTokenException;
import com.hoperun.framework.ex.ErrorMessage;
import com.hoperun.framework.ex.XHZException;
import com.hoperun.framework.ex.XHZValidationException;
import com.hoperun.framework.message.NLS;
import com.hoperun.framework.util.Constant;
import com.hoperun.framework.web.util.WebUtils;

public class XHZSimpleMappingExceptionResolver extends
		SimpleMappingExceptionResolver {

	private static final Logger LOGGER = LoggerFactory
			.getLogger(XHZSimpleMappingExceptionResolver.class);

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	protected ModelAndView doResolveException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {
		/** 消息体 **/
		ErrorMessage errorMessage = new ErrorMessage();
		errorMessage.setStatus("error");

		/** oauth2 */
		if (ex instanceof AccessTokenException) {
			/** JSON格式返回 */
			MappingJackson2JsonView jsonView = new MappingJackson2JsonView();

			errorMessage.setError("error");
			errorMessage.setErrorDescription(((AccessTokenException) ex).getMessage());

			jsonView.addStaticAttribute("data", errorMessage) ;
			ModelAndView modelAndView = new ModelAndView();
			modelAndView.setView(jsonView);

			return modelAndView;
		}

		/** 选择视图ModelAndView暴露错误 */
		String viewName = super.determineViewName(ex, request);
		LOGGER.debug(" XHZSimpleMappingExceptionResolver viewName is {} ",
				viewName);
		if (StringUtils.isEmpty(viewName)) {
			return null;
		}

		/** 判断是否是异步请求 */
		if (!WebUtils.isAjaxRequest(request) && !WebUtils.isWapRequest(request)) {
			if (ex instanceof UnauthenticatedException) {
				return super.getModelAndView("alone:admin.login", ex, request);
			}
			if (ex instanceof AuthorizationException) {
				return super.getModelAndView(viewName, ex, request);
			}

			Integer statusCode = determineStatusCode(request, viewName);
			if (statusCode != null) {
				applyStatusCodeIfPossible(request, response, statusCode);
			}

			return super.getModelAndView(viewName, ex, request);
		}
		/** JSON格式返回 */
		MappingJackson2JsonView view = new MappingJackson2JsonView();
		String msg = ex.getMessage();
		Map attributes = Maps.newHashMap();
		attributes.put("message", msg);
		int code = Constant.ERROR;
		if (ex instanceof XHZException) {
			code = ((XHZException) ex).getCode();
			code = (Constant.SUCCESS == code) ? Constant.ERROR : code;
			attributes.put("code", code);
			view.setAttributesMap(attributes);
		}
		/** 校验性错误 */
		if (ex instanceof XHZValidationException) {
			XHZValidationException be = (XHZValidationException) ex;
			msg = be.getErrorMessages();
			attributes.put("message", msg);
			code = (Constant.SUCCESS == code) ? Constant.ERROR : code;
			attributes.put("code", code);
			view.setAttributesMap(attributes);
		}

		if (ex instanceof MaxUploadSizeExceededException) {
			attributes.put("message", NLS.getMessage("fileMax"));
			code = (Constant.SUCCESS == code) ? Constant.ERROR : code;
			attributes.put("code", code);
			view.setAttributesMap(attributes);
		}

		/** 未授权 */
		if (ex instanceof UnauthenticatedException) {
			code = (Constant.SUCCESS == code) ? Constant.ERROR : code;
			attributes.put("code", code);
			view.setAttributesMap(attributes);
		}

		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setView(view);
		LOGGER.debug(" resopnse json  data is {}",
				JSONObject.toJSONString(attributes));
		return modelAndView;

	}
}
